#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2019/5/15 11:12
# @Author  : CHEN Wang
# @Site    :
# @File    : my_logger.py
# @Software: PyCharm

"""
脚本说明: 日志的相关配置, 支持同步向控制台输出，支持同步或者异步打印日志到文件同时可以控制是否向控制台输出
"""

import time
import datetime
import os
import sys
import logging
import threading
import queue
from logging.handlers import RotatingFileHandler
from quant_researcher.quant.project_tool.conf import LOCAL_CONF
from quant_researcher.quant.project_tool.localize import log_path

DEBUG = LOCAL_CONF.getint('logging', 'debug')
ASYNC = LOCAL_CONF.getint('logging', 'async')
WINDOWS = LOCAL_CONF.getint('logging', 'print_2_windows')
PRINT_KEY_INFORMATION = LOCAL_CONF.getint('logging', 'print_key_information', fallback=0)
LOG_LEVEL = LOCAL_CONF.getint('logging', 'log-level')
LOG_FMT = '%(asctime)s-%(funcName)s-G:%(lineno)d-%(levelname)s: %(message)s'

try:
    log_file_name = '{}{}wqr_{}_{}.log'.format(
        log_path,
        os.sep,
        os.path.basename(sys.argv[0]).split('.py')[0],
        str(datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S'))
    )
except:
    log_file_name = '{}{}wqr_{}.log'.format(
        log_path,
        os.sep,
        str(datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S'))
    )


class logging2(threading.Thread):
    AQueue = queue.Queue(100000)
    nPID = os.getpid()
    Adt = datetime.datetime.now().strftime('%Y%m%d')
    nCount = 1

    def __init__(self, threadID, log_type, log_file_name, log_level, format, print_2_windows):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.log_type = log_type
        format = 'async-log-' + format

        formatter = logging.Formatter(format)
        self.logger = logging.getLogger(log_file_name)

        self.rHandler = RotatingFileHandler(log_file_name, maxBytes=10 * 1024 * 1024,
                                            backupCount=10, mode='a', encoding='utf-8')
        self.rHandler.setFormatter(formatter)

        if log_level == 10 or log_level == 'DEBUG':
            self.logger.setLevel(level=logging.DEBUG)
            self.rHandler.setLevel(logging.DEBUG)
        elif log_level == 20 or log_level == 'INFO':
            self.logger.setLevel(level=logging.INFO)
            self.rHandler.setLevel(logging.INFO)
        elif log_level == 30 or log_level == 'WARNING':
            self.logger.setLevel(level=logging.WARN)
            self.rHandler.setLevel(logging.WARN)
        elif log_level == 40 or log_level == 'ERROR':
            self.logger.setLevel(level=logging.ERROR)
            self.rHandler.setLevel(logging.ERROR)
        elif log_level == 50 or log_level == 'CRITICAL':
            self.logger.setLevel(level=logging.CRITICAL)
            self.rHandler.setLevel(logging.CRITICAL)

        self.logger.addHandler(self.rHandler)

        if print_2_windows:
            self.console = logging.StreamHandler()
            self.console.setFormatter(formatter)
            if log_level == 10 or log_level == 'DEBUG':
                self.logger.setLevel(level=logging.DEBUG)
                self.console.setLevel(logging.DEBUG)
            elif log_level == 20 or log_level == 'INFO':
                self.logger.setLevel(level=logging.INFO)
                self.console.setLevel(logging.INFO)
            elif log_level == 30 or log_level == 'WARNING':
                self.logger.setLevel(level=logging.WARN)
                self.console.setLevel(logging.WARN)
            elif log_level == 40 or log_level == 'ERROR':
                self.logger.setLevel(level=logging.ERROR)
                self.console.setLevel(logging.ERROR)
            elif log_level == 50 or log_level == 'CRITICAL':
                self.logger.setLevel(level=logging.CRITICAL)
                self.console.setLevel(logging.CRITICAL)
            self.logger.addHandler(self.console)

    # 如果跨天了，则重新生成新的文件名
    def reSetLog(self):
        AdtTemp = datetime.datetime.now().strftime('%Y%m%d')
        # 比较新的时间
        if AdtTemp == logging2.Adt:
            return (True)
        logging2.Adt = AdtTemp
        logfile = "log_" + self.module + "_" + str(logging2.nPID) + "_" + str(AdtTemp) + ".log"
        self.rHandler = RotatingFileHandler(logfile, maxBytes=1 * 1024, backupCount=10)

        self.logger.addHandler(self.rHandler)
        self.logger.addHandler(self.console)
        logging2.nCount += 1

    def run(self):
        print("开启日志线程：" + self.log_type)
        i = 0
        while True:
            # data = "queue test data"
            # debug(data)
            # print("Queuesize: %s" % (logging2.AQueue.qsize()))
            self.reSetLog()
            if not logging2.AQueue.empty():
                # 从队列获取日志消息
                data = logging2.AQueue.get()
                # 解析日志消息，格式：日志级别，内容
                level = list(data.keys())[0]
                content = data.get(level)
                # 把内容按分隔符|解析成list传入参数
                lstContent = list(content.split('|'))
                if level == 'DEBUG':
                    self.logger.debug(*lstContent)
                elif level == 'INFO':
                    self.logger.info(*lstContent)
                elif level == 'WARNING':
                    self.logger.warning(*lstContent)
                elif level == 'ERROR':
                    self.logger.error(*lstContent)
            else:
                time.sleep(0.5)
        print("退出线程：" + self.log_type)

    def debug(*content):
        logMsg = content[1]
        logging2.AQueue.put({'DEBUG': logMsg})

    def info(*content):
        logMsg = content[1]
        logging2.AQueue.put({'INFO': logMsg})

    def warning(*content):
        logMsg = content[1]
        logging2.AQueue.put({'WARNING': logMsg})

    def error(*content):
        logMsg = content[1]
        logging2.AQueue.put({'ERROR': logMsg})


if not DEBUG:  # DEBUG=False, 即上生产, 打印日志到文件中
    if not ASYNC:  # 同步打印日志到文件
        fh = logging.FileHandler(filename=log_file_name, mode='a', encoding='utf-8')
        formatter = logging.Formatter(LOG_FMT)
        logging.basicConfig(handlers=[fh], level=LOG_LEVEL, format=LOG_FMT)
        LOG = logging.getLogger(log_file_name)
        if WINDOWS:  # 同时也打印到前端
            console = logging.StreamHandler()
            console.setFormatter(formatter)
            console.setLevel(LOG_LEVEL)
            LOG.addHandler(console)
        LOG.setLevel(LOG_LEVEL)

    else:          # 异步打印日志到文件
        # 创建新日志线程
        LOG = logging2(threadID=1, log_type="Thread-log", log_file_name=log_file_name,
                       log_level=LOG_LEVEL, format=LOG_FMT, print_2_windows=WINDOWS)
        # 开启新日志线程
        LOG.start()

else:
    # 下面声明的logger会向控制台输出日志
    logging.basicConfig(level=LOG_LEVEL, format=LOG_FMT)
    LOG = logging.getLogger(log_file_name)
    LOG.setLevel(LOG_LEVEL)


def test_log():
    # 测试不同日志输出方式的效率
    the_day = '2020-01-01'
    n = 1000
    while n:
        LOG.debug(f'{the_day}，看起来不像是一个交易日')
        LOG.info(f'{the_day}，看起来不像是一个交易日')
        LOG.warning(f'{the_day}，看起来不像是一个交易日')
        LOG.error(f'{the_day}，看起来不像是一个交易日')
        n = n-1

    return 1


if __name__ == '__main__':
    # 测试
    start_time = datetime.datetime.now()  # 程序开始时间
    x = test_log()
    over_time = datetime.datetime.now()  # 程序结束时间
    total_sec = (over_time - start_time).total_seconds()
    print(total_sec)

